This code, somewhat surprisingly, generates Fibonacci numbers.
def fib(n):
return (4 << n*(3+n)) // ((4 << 2*n) - (2 << n) - 1) & ((2 << n) - 1)
In this blog post, I’ll explain where it comes from and how it works.
Before getting to explaining, I’ll give a whirlwind background overview of Fibonacci numbers and how to compute them. If you’re already a maths whiz, you can skip most of the introduction, quickly skim the section “Generating functions” and then read “An integer formula”.
Overview
The Fibonacci numbers are a well-known sequence of numbers:
The
I’ve chosen to start the sequence at index 0 rather than the more usual 1.
Computing Fibonacci numbers
There’s a few different reasonably well-known ways of computing the sequence. The obvious recursive implementation is slow:
def fib_recursive(n):
if n < 2: return 1
return fib_recursive(n - 1) + fib_recursive(n - 2)
An iterative implementation works in
def fib_iter(n):
a, b = 1, 1
for _ in xrange(n):
a, b = a + b, a
return b
And a slightly less well-known matrix power implementation works in
def fib_matpow(n):
m = numpy.matrix('1 1 ; 1 0') ** n
return m.item(0)
The last method works by considering the a
and b
in fib_iter
as sequences, and noting that
From which follows
and so if
then
It’s
Another method is to find a closed form for the solution of the recurrence relation. This leads to the real-valued formula:
def fib_phi(n):
phi = (1 + math.sqrt(5)) / 2.0
psi = (1 - math.sqrt(5)) / 2.0
return int((phi ** (n+1) - psi ** (n+1)) / math.sqrt(5))
Generating Functions
A generating function for an arbitrary sequence
Now,
Multiplying by
If we let
and simplifying,
We can solve this equation for
It’s surprising that we’ve managed to find a small and simple formula which captures all of the Fibonacci numbers, but it’s not yet obvious how we can use it. We’ll get to that in the next section.
A technical aside is that we’re going to want to evaluate
An integer formula
Now we’re ready to start understanding the Python code.
To get the intuition behind the formula, we’ll evaluate the generating function
Interestingly, we can see some Fibonacci numbers in this decimal expansion:
In this example, the Fibonacci numbers are spaced out at multiples of
But, for any value of
Also, since we’d like to use integer maths (because it’s easier to code), let’s multiply by
If we take this result modulo
Before proceeding, let’s switch to base 2 rather than base 10, which changes nothing but will make it easier to program.
Now all that’s left is to pick a value of
So! Putting that together:
If we use left-shift notation that’s available in python, where
Observing that &
) of
def fib(n):
return (4 << n*(3+n)) // ((4 << 2*n) - (2 << n) - 1) & ((2 << n) - 1)
Although it’s curious to find a non-iterative, closed-form solution, this isn’t a practical method at all. We’re doing integer arithmetic with integers of size